"""
@Author    : ghenyar
@Time      : 2025/9/5 13:17
@File      : decorator
@Desc      :  装饰器
"""
import json

import user_agents
from fastapi import Request
from functools import wraps
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
from app.common.model_querier import ModelQuerier
from app.models.admin_model import AdminModel, AdminLogModel


def log_operation(log_message: Optional[str] = None, types: int = 100):
    """
    操作日志修饰器
    :param log_message: 日志内容
    :param types: 操作类型  0:登录  1:新增  2:修改  3:删除 4:上传  100:其他
    :return:
    """

    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            request: Request = kwargs.get('request')
            # 解析 User-Agent
            user_agent_str = request.headers.get('user-agent')

            act_type = {
                0: "登录",
                1: "新增",
                2: "编辑",
                3: "删除",
                4: "上传",
                100: "",
            }
            # 操作日志数据
            act_text = act_type.get(types, 100)
            desc_message = "{}{}".format(act_text, log_message) if log_message else act_text
            logs = {
                "method": request.method,
                "types": types,
                "desc_message": desc_message,
                "ip": request.client.host,
                "uri": request.url.path,
            }

            if user_agent_str:
                user_agent = user_agents.parse(user_agent_str)
                logs["os_name"] = f"{user_agent.os.family}({user_agent.os.version_string})"
                logs["web_browser"] = f"{user_agent.browser.family}({user_agent.browser.version_string})"

            # 获取请求体参数
            try:
                body_params = await request.json()
            except Exception:
                body_params = dict(request.query_params)

            # 获取db
            db = kwargs.get('db')
            if db is None:
                # 如果不在kwargs中，尝试从args中查找
                for arg in args:
                    if isinstance(arg, AsyncSession):
                        db = arg
                        break

            # 请求参数
            if "password" in body_params:
                del body_params["password"]

            # 检查是否只有 _t 字段且值为字符串
            if body_params == {"_t": body_params.get("_t")} and isinstance(body_params.get("_t"), str):
                logs["req_param"] = ""
            else:
                logs["req_param"] = json.dumps(body_params)

            if hasattr(request.state, "admin_id"):
                logs["admin_id"] = request.state.admin_id
                admin = await ModelQuerier(db, AdminModel).get_by_id(request.state.admin_id)
                logs["account"] = admin.account
            else:
                logs["admin_id"] = 0
                logs["account"] = body_params.get("username")

            response = await func(*args, **kwargs)
            logs["status_code"] = response.code
            if response.code == 200 or response.code == 201 or response.code == 204:
                logs["result_msg"] = "登录成功" if types == 0 else "操作成功"
            else:
                logs["result_msg"] = "登录失败" if types == 0 else "操作失败"

            logs["result"] = json.dumps(response.__dict__, ensure_ascii=False, default=str)

            try:
                admin_log = AdminLogModel(**logs)
                db.add(admin_log)
                await db.commit()
            except Exception as e:
                await db.rollback()
                print("error:", e)

            return response

        return wrapper

    return decorator
